package cn.fr4nk.crawler.task;

import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.LinkedBlockingQueue;

import org.apache.commons.lang3.StringUtils;

import cn.fr4nk.crawler.pojo.TaskResult;


public class TaskStore implements TaskStoreApi {

	private static ConcurrentMap<String, CrawlerTask> completedTaskMap;
	private static ConcurrentMap<String, FailedTask> failedTaskMap;

	private static volatile TaskStore instance = null;

	public static TaskStore getInstance() {
		if (null == instance) {
			synchronized (TaskStore.class) {
				if (null == instance)
					instance = new TaskStore();
			}
		}
		return instance;
	}

	private BlockingQueue<TaskResult> resultQueue;
	private BlockingQueue<CrawlerTask> todoQueue;
	private BlockingQueue<CrawlerTask> failedQueue; // 入该队列，就表示任务失败过

	private TaskStore() {
		todoQueue = new LinkedBlockingQueue<CrawlerTask>();
		failedQueue = new LinkedBlockingQueue<CrawlerTask>();
		resultQueue = new LinkedBlockingQueue<TaskResult>();
		completedTaskMap = new ConcurrentHashMap<String, CrawlerTask>();
		failedTaskMap = new ConcurrentHashMap<String, FailedTask>();
	}

	@Override
	public void addCompleted(CrawlerTask task) throws Exception {
		if (null != task && StringUtils.isNotEmpty(task.getUrl())) {
			completedTaskMap.putIfAbsent(task.getUrl(), task);
		}
	}

	/**
	 * 加入失败任务队列
	 */
	@Override
	public void addFailedTask(CrawlerTask task) throws Exception {
		failedQueue.put(task);
	}
	
	public void addFailedTaskMap(FailedTask task) throws Exception{
		String key = task.getTask().getUrl();
		failedTaskMap.put(key, task);
	}
	
	public FailedTask getFailedTaskFromMap(String key) {
		return failedTaskMap.get(key);
	}

	@Override
	public void addTaskResult(TaskResult result) throws Exception {
		resultQueue.put(result);
	}

	@Override
	public void addTodo(CrawlerTask task) throws Exception {
		todoQueue.put(task);
	}

	@Override
	public boolean containsCompleted(CrawlerTask task) {
		if (null == task || StringUtils.isNotEmpty(task.getUrl())) {
			return false;
		}
		return completedTaskMap.containsKey(task.getUrl());
	}

	public boolean containsFailedTask(FailedTask task) {
		if (null == task || null == task.getTask() || StringUtils.isNotEmpty(task.getTask().getUrl())) {
			return false;
		}
		return failedTaskMap.containsKey(task.getTask().getUrl());
	}
	
	public void updateFailedTask(FailedTask task) {
		failedTaskMap.put(task.getTask().getUrl(), task);
	}
	

	public boolean containsFailedTaskKey(String key) {
		return failedTaskMap.containsKey(key);
	}

	@Override
	public CrawlerTask fetchFailedTask() throws InterruptedException {
		return failedQueue.take();
	}

	@Override
	public TaskResult fetchTaskResult() throws Exception {
		return resultQueue.take();
	}

	@Override
	public CrawlerTask fetchTodo() throws InterruptedException {
		return todoQueue.take();
	}

	@Override
	public Set<String> getCompletedTasks() {
		return completedTaskMap.keySet();
	}

}
